package com.kgc.scd.service.impl;

import com.kgc.scd.bean.Order;
import com.kgc.scd.bean.Seckill;
import com.kgc.scd.config.SeckillConfig;
import com.kgc.scd.service.SeckillBuyService;
import com.kgc.scd.service.SeckillTradeOrderFeignService;
import com.kgc.scd.util.RedisUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;

/**
 * Created On : 2022/6/7.
 * <p>
 * Author     : 98730
 * <p>
 * Description: 秒杀抢购业务实现类
 */
@Slf4j
@Service
public class SeckillBuyServiceImpl implements SeckillBuyService {

    @Autowired
    private RedisUtils redisUtils;

    @Autowired
    private SeckillConfig seckillConfig;

    @Autowired
    private SeckillTradeOrderFeignService seckillTradeOrderFeignService;

    @Override
    public boolean limitBuyUserCount(String prodId) {
        // 请求数，限制在设定的值以内，比如库存数量的二倍
        return redisUtils.incr(prodId, 1) > seckillConfig.getProdStockCount() * 2;
    }

    @Override
    public void initProdStock2Redis(String prodId) {
        // 判断redis中，当前商品是否已经存在库存数据，如果存在，不需要再次同步，如果不存在才需要同步
        if (ObjectUtils.isEmpty(redisUtils.get(seckillConfig.getProdStockPrefix() + ":" + prodId))){
            // 将商品库存存入redis
            redisUtils.set(seckillConfig.getProdStockPrefix() + ":" + prodId, seckillConfig.getProdStockCount());
            log.info("****** 初始化商品：{}，库存到redis缓存 ******",prodId);

        }
    }

    @Override
    public boolean checkProdStockEnough(String prodId, Integer buyCount) {
        // redis获取商品库存，跟购买数量进行比较，必须大于等于
        return Integer.valueOf(redisUtils.get(seckillConfig.getProdStockPrefix() + ":" + prodId).toString()) >= buyCount;
    }

    @Override
    public boolean checkSeckillUserBought(String userId, String prodId) {
        // 借助redis的分布式锁：·setnx，根据用户编号和商品编号，进行锁定
        return !redisUtils.lock(seckillConfig.getLockUserPrefix() + ":" + userId + ":" + prodId, null, seckillConfig.getLockUserTime());
    }

    @Override
    public boolean checkProdStockLocked(String prodId) {
        // 借助redis的分布式锁：setnx，直接尝试库存上锁，如果成功，redis中的库存还没被锁定，可以购买，如果失败，代表库存已经被锁定，不可以购买
        return !redisUtils.lock(seckillConfig.getProdStockLockPrefix() + ":" + prodId,null,seckillConfig.getProdStockLockTime());
    }

    @Override
    public boolean subProdStock(String prodId, Integer buyCount) {
        // 扣减缓存中的商品库存，同时可以发送异步消息队列，更新数据库的库存，保证数据一致
        return redisUtils.decr(seckillConfig.getProdStockPrefix() + ":" + prodId,buyCount) < 0;
    }

    @Override
    public void unlockProdStock(String prodId) {
        // 释放库存锁
        redisUtils.delLock(seckillConfig.getProdStockLockPrefix() + ":" + prodId);
    }

    @Override
    public Order createOrder(String userId, String seckillId) {

        //远程调用，订单中心的接口，返回订单编号（实际因该是订单实体）
        return seckillTradeOrderFeignService.invokeCreateTradeOrderFeign(userId,seckillId);
    }

}
